package org.jeecg.modules.carInformationUpload.controller;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.modules.carInformationUpload.entity.CarInformationUpload;
import org.jeecg.modules.carInformationUpload.entity.EntryExitStatus;
import org.jeecg.modules.carInformationUpload.service.ICarInformationUploadService;
import org.jeecg.modules.carInformationUpload.util.Base64ToMultipartFile;
import org.jeecg.modules.carLedger.entity.CarLedger;
import org.jeecg.modules.carLedger.service.ICarLedgerService;
import org.jeecg.modules.carRecord.entity.CarRecord;
import org.jeecg.modules.carRecord.service.ICarRecordService;
import org.jeecg.modules.carRegister.entity.CarRegister;
import org.jeecg.modules.carRegister.service.ICarRegisterService;
import org.jeecg.modules.networking.service.INetWorkingService;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;

/**
 * @Description: 进出厂车辆信息上传表
 * @Author: jeecg-boot
 * @Date:   2024-07-23
 * @Version: V1.0
 */
@Api(tags="进出厂车辆信息上传表")
@RestController
@RequestMapping("/carInformationUpload/carInformationUpload")
@Slf4j
public class CarInformationUploadController extends JeecgController<CarInformationUpload, ICarInformationUploadService> {
	@Value(value = "${jeecg.uploadType}")
	private String uploadType;
	@Autowired
	private ICarInformationUploadService carInformationUploadService;
	@Autowired
	private ICarRecordService carRecordService;
	@Autowired
	private ICarLedgerService carLedgerService;
	@Autowired
	private ICarRegisterService carRegisterService;
	@Autowired
	private INetWorkingService netWorkingService;

	/**
	 * 分页列表查询
	 *
	 * @param carInformationUpload 对象
	 * @param pageNo 页数
	 * @param pageSize 每页大小
	 * @param req 请求
	 * @return Result
	 */
	@AutoLog(value = "进出厂车辆信息上传表-分页列表查询")
	@ApiOperation(value="进出厂车辆信息上传表-分页列表查询", notes="进出厂车辆信息上传表-分页列表查询")
	@GetMapping(value = "/list")
	public Result<?> queryPageList(CarInformationUpload carInformationUpload,
								   @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
								   @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
								   HttpServletRequest req) {
		QueryWrapper<CarInformationUpload> queryWrapper = QueryGenerator.initQueryWrapper(carInformationUpload, req.getParameterMap());
		Page<CarInformationUpload> page = new Page<CarInformationUpload>(pageNo, pageSize);
		IPage<CarInformationUpload> pageList = carInformationUploadService.page(page, queryWrapper);
		return Result.OK(pageList);
	}

	 @AutoLog(value = "进出厂车辆信息上传表-对外-分页列表查询")
	 @ApiOperation(value="进出厂车辆信息上传表-对外-分页列表查询", notes="进出厂车辆信息上传表-对外-分页列表查询")
	 @GetMapping(value = "/m/list")
	 public Result<?> mQueryPageList(CarInformationUpload carInformationUpload,
									@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
									@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
									HttpServletRequest req) {
		 QueryWrapper<CarInformationUpload> queryWrapper = QueryGenerator.initQueryWrapper(carInformationUpload, req.getParameterMap());
		 queryWrapper.orderByDesc("create_time");
		 Page<CarInformationUpload> page = new Page<CarInformationUpload>(pageNo, pageSize);
		 IPage<CarInformationUpload> pageList = carInformationUploadService.page(page, queryWrapper);
		 return Result.OK(pageList);
	 }

	/**
	 *   添加
	 *
	 * @param jsonObject 对象
	 * @return Result
	 */
	@AutoLog(value = "进出厂车辆信息上传表-移动端-上传")
	@ApiOperation(value="进出厂车辆信息上传表-移动端-上传", notes="进出厂车辆信息上传表-移动端-上传")
	@PostMapping(value = "/m/appUpload")
	public Result<?> appUpload(@RequestBody JSONObject jsonObject){
		String gateNumber = jsonObject.getString("gateNumber");
		String barrierGateNumber = jsonObject.getString("barrierGateNumber");
		EntryExitStatus entryExitStatus = EntryExitStatus.fromValue(jsonObject.getString("entryExitStatus"));
		String carType = jsonObject.getString("carType");
		String plateNo = jsonObject.getString("plateNo");
		String plateColor = jsonObject.getString("plateColor");
		String entryExitTime = jsonObject.getString("entryExitTime");
		String entryExitPic = jsonObject.getString("entryExitPic");
		Date date = stringToDate(entryExitTime);
		if (entryExitStatus == EntryExitStatus.ENTRY) {
			if ("1".equals(carType)) { // 入台账
				CarRegister oneByPlateNo = carRegisterService.getLastAllowByPlateNo(plateNo);
				if (oneByPlateNo != null) {
					CarInformationUpload carInformationUpload = getInformationUpload(oneByPlateNo,
							gateNumber, barrierGateNumber, entryExitStatus, date, entryExitPic, entryExitPic);
					CarLedger carLedger = getCarLedger(oneByPlateNo, gateNumber,
							barrierGateNumber, date, entryExitPic, null);
					if (1 != oneByPlateNo.getWhiteList()){
						oneByPlateNo.setEntryStatus(1); // 已入场
					}
				 	carRegisterService.updateById(oneByPlateNo);
					carInformationUploadService.save(carInformationUpload);
					carLedgerService.save(carLedger);
				} else {
					return Result.error("该车辆未登记!");
				}
			}
			createOrUpdateCarRecord(plateNo, plateColor, barrierGateNumber, date, entryExitPic, true);
		} else if (entryExitStatus == EntryExitStatus.EXIT) {
			if ("1".equals(carType)) { // 入台账
				CarLedger lastByPlateNo = carLedgerService.getLastByPlateNo(plateNo);
				if (lastByPlateNo != null) {
					CarInformationUpload carInformationUpload = getInformationUpload(lastByPlateNo,
							gateNumber, barrierGateNumber, entryExitStatus, date, entryExitPic, entryExitPic);
					lastByPlateNo.setExitPic(entryExitPic).setExitTime(date);
					carLedgerService.updateById(lastByPlateNo);
					carInformationUploadService.save(carInformationUpload);
				} else {
					CarRegister oneByPlateNo = carRegisterService.getOneByPlateNo(plateNo);
					if (oneByPlateNo != null) {
						CarLedger carLedger = new CarLedger();
						BeanUtils.copyProperties(oneByPlateNo, carLedger);
						carLedger.setId(null).setCreateTime(null).setCreateBy(null).setUpdateBy(null)
								.setUpdateTime(null).setGateNumber(gateNumber)
								.setBarrierGateNumber(barrierGateNumber)
								.setExitTime(date).setExitPic(entryExitPic);
						CarInformationUpload carInformationUpload = getInformationUpload(oneByPlateNo,
								gateNumber, barrierGateNumber, entryExitStatus, date, entryExitPic, entryExitPic);
						carLedgerService.save(carLedger);
						carInformationUploadService.save(carInformationUpload);
					}
				}
			}
			createOrUpdateCarRecord(plateNo, plateColor, barrierGateNumber, date, entryExitPic, false);
		} else {
			return Result.error("进出场状态不正确");
		}
		return Result.OK("上传成功", null);
	}

	 /**
	  *   添加
	  *
	  * @param jsonObject 对象
	  * @return Result
	  */
	 @AutoLog(value = "进出厂车辆信息上传表-客户端-上传")
	 @ApiOperation(value="进出厂车辆信息上传表-客户端-上传", notes="进出厂车辆信息上传表-客户端-上传")
	 @PostMapping(value = "/m/upload")
	 public Result<?> mUpload(@RequestBody JSONObject jsonObject) {
		 String gateNumber = jsonObject.getString("gateNumber");
		 String barrierGateNumber = jsonObject.getString("barrierGateNumber");
		 String carType = jsonObject.getString("carType");
		 EntryExitStatus entryExitStatus = EntryExitStatus.fromValue(jsonObject.getString("entryExitStatus"));
		 String plateNo = jsonObject.getString("plateNo");
		 String plateColor = jsonObject.getString("plateColor");
		 String entryExitTime = jsonObject.getString("entryExitTime");
		 String entryExitPic = jsonObject.getString("entryExitPic");
		 String highPic = jsonObject.getString("highPic");
		 MultipartFile multipartFile = new Base64ToMultipartFile(entryExitPic, "png", "image/png");
		 String bizPath = DateUtil.formatDate(new Date());
		 String savePath = CommonUtils.upload(multipartFile, bizPath, uploadType);
		 String highPath = null;
		 if (highPic != null && !highPic.isEmpty()){
			 MultipartFile highFile = new Base64ToMultipartFile(highPic, "png", "image/png");
			 highPath = CommonUtils.upload(highFile, bizPath, uploadType);
		 }
		 Date date = stringToDate(entryExitTime);
		 if (entryExitStatus == EntryExitStatus.ENTRY) {
			 if ("1".equals(carType)) {//入台账
				 CarRegister oneByPlateNo = carRegisterService.getLastAllowByPlateNo(plateNo);
				 if (oneByPlateNo != null) {
					 CarInformationUpload carInformationUpload = getInformationUpload(oneByPlateNo, gateNumber, barrierGateNumber, entryExitStatus, date, savePath, highPath);
					 CarLedger carLedger = getCarLedger(oneByPlateNo, gateNumber,
							 barrierGateNumber, date, savePath, highPath);
					 if (1 != oneByPlateNo.getWhiteList()){
						 oneByPlateNo.setEntryStatus(1); // 已入场
					 }
					 carRegisterService.updateById(oneByPlateNo);
					 carLedgerService.save(carLedger);
					 uploadAndSaveCarInformation(carInformationUpload);
				 }
			 }
			 createOrUpdateCarRecord(plateNo, plateColor, barrierGateNumber, date, savePath, true);
		 } else if (entryExitStatus == EntryExitStatus.EXIT) {
			 if ("1".equals(carType)) {//入台账
				 CarLedger lastByPlateNo = carLedgerService.getLastByPlateNo(plateNo);
				 if (lastByPlateNo != null) {
					 CarInformationUpload carInformationUpload = getInformationUpload(lastByPlateNo, gateNumber, barrierGateNumber, entryExitStatus, date, savePath, highPath);
					 lastByPlateNo.setExitPic(savePath).setExitTime(date).setExitHighPic(highPath);
					 carLedgerService.updateById(lastByPlateNo);
					 uploadAndSaveCarInformation(carInformationUpload);
				 } else {
					 CarRegister oneByPlateNo = carRegisterService.getOneByPlateNo(plateNo);
					 if (oneByPlateNo != null) {
						 CarLedger carLedger = new CarLedger();
						 BeanUtils.copyProperties(oneByPlateNo, carLedger);
						 carLedger.setId(null).setCreateTime(null).setCreateBy(null).setUpdateBy(null)
								 .setUpdateTime(null).setGateNumber(gateNumber)
								 .setBarrierGateNumber(barrierGateNumber)
								 .setExitTime(date).setExitPic(savePath).setExitHighPic(highPath);
						 carLedger.setGoods(oneByPlateNo.getGoods()).setFreightVolume(oneByPlateNo.getFreightVolume());
						 if (oneByPlateNo.getTransportStatus() == 1){
							 carLedger.setInTransportGoods(oneByPlateNo.getGoods()).setInFreightVolume(oneByPlateNo.getFreightVolume());
						 } else {
							 carLedger.setOutTransportGoods(oneByPlateNo.getGoods()).setOutFreightVolume(oneByPlateNo.getFreightVolume());
						 }
						 CarInformationUpload carInformationUpload = getInformationUpload(oneByPlateNo, gateNumber, barrierGateNumber, entryExitStatus, date, savePath, highPath);
						 carLedgerService.save(carLedger);
						 uploadAndSaveCarInformation(carInformationUpload);
                     }
				 }
			 }
			 createOrUpdateCarRecord(plateNo, plateColor, barrierGateNumber, date, savePath, false);
		 } else {
			 return Result.error("进出场状态不正确");
		 }
		 return Result.OK("上传成功", null);
	 }

	private void uploadAndSaveCarInformation(CarInformationUpload carInformationUpload){
		new Thread(() -> {
			try {
				JSONObject response = netWorkingService.putVehiclePassRecords(carInformationUpload);
				Integer code = response.getInteger("code");
				if (code == 200) {
					carInformationUpload.setUploadStatus("1");
				} else {
					log.warn("接口返回错误结果: {}", response);
				}
			} catch (Exception e) {
				log.error(e.getMessage(), e);
			}
			carInformationUploadService.save(carInformationUpload);
		}).start();
	}

	private void createOrUpdateCarRecord(String plateNo, String plateColor, String barrierGateNumber,
										 Date date, String savePath, boolean isEntry) {
		CarRecord carRecord = isEntry ? new CarRecord() : carRecordService.getLastByPlateNo(plateNo);
		if (carRecord == null) {
			carRecord = new CarRecord();
		}
		carRecord.setPlateNo(plateNo).setPlateColor(plateColor).setBarrierGateNumber(barrierGateNumber)
				.setEntryPic(isEntry ? savePath : null).setEntryTime(isEntry ? date : null)
				.setExitPic(!isEntry ? savePath : null).setExitTime(!isEntry ? date : null);
		if (carRecord.getId() == null || carRecord.getId().isEmpty()) {
			carRecordService.save(carRecord);
		} else {
			carRecordService.updateById(carRecord);
		}
	}

	private static @NotNull CarLedger getCarLedger(CarRegister oneByPlateNo, String gateNumber,
												   String barrierGateNumber, Date date,
												   String savePath, String highPath) {
		CarLedger carLedger = new CarLedger();
		BeanUtils.copyProperties(oneByPlateNo, carLedger);
		carLedger.setGateNumber(gateNumber).setBarrierGateNumber(barrierGateNumber)
				.setEntryTime(date).setEntryPic(savePath).setId(null).setCreateTime(null)
				.setCreateBy(null).setUpdateBy(null).setUpdateTime(null)
				.setEntryHighPic(highPath);
		if (oneByPlateNo.getTransportStatus() == 0) {
			carLedger.setOutTransportGoods(oneByPlateNo.getGoods());
			carLedger.setOutFreightVolume(oneByPlateNo.getFreightVolume());
		} else {
			carLedger.setInTransportGoods(oneByPlateNo.getGoods());
			carLedger.setInFreightVolume(oneByPlateNo.getFreightVolume());
		}
		return carLedger;
	}

	private static @NotNull CarInformationUpload getInformationUpload(CarLedger carLedger, String gateNumber, String barrierGateNumber, EntryExitStatus entryExitStatus, Date date, String savePath, String highPath) {
		CarInformationUpload carInformationUpload = new CarInformationUpload();
		BeanUtils.copyProperties(carLedger, carInformationUpload);
		carInformationUpload.setGateNumber(gateNumber).setBarrierGateNumber(barrierGateNumber)
				.setEntryExitStatus(entryExitStatus.getValue()).setEntryExitTime(date)
				.setEntryExitPic(savePath).setHighPic(highPath).setId(null).setCreateTime(null)
				.setCreateBy(null).setUpdateBy(null).setUpdateTime(null);
		return carInformationUpload;
	}

	private static @NotNull CarInformationUpload getInformationUpload(CarRegister oneByPlateNo,
																	  String gateNumber, String barrierGateNumber,
																	  EntryExitStatus entryExitStatus, Date date,
																	  String savePath, String highPath) {
		CarInformationUpload carInformationUpload = new CarInformationUpload();
		BeanUtils.copyProperties(oneByPlateNo, carInformationUpload);
		carInformationUpload.setGateNumber(gateNumber).setBarrierGateNumber(barrierGateNumber)
				.setEntryExitStatus(entryExitStatus.getValue()).setEntryExitTime(date)
				.setEntryExitPic(savePath).setHighPic(highPath).setId(null).setCreateTime(null)
				.setCreateBy(null).setUpdateBy(null).setUpdateTime(null);
		return carInformationUpload;
	}

	/**
	 *   添加
	 *
	 * @param carInformationUpload 对象
	 * @return Result
	 */
	@AutoLog(value = "进出厂车辆信息上传表-添加")
	@ApiOperation(value="进出厂车辆信息上传表-添加", notes="进出厂车辆信息上传表-添加")
	@PostMapping(value = "/add")
	public Result<?> add(@RequestBody CarInformationUpload carInformationUpload) {
		carInformationUploadService.save(carInformationUpload);
		return Result.OK("添加成功！");
	}

	/**
	 *  编辑
	 *
	 * @param carInformationUpload 对象
	 * @return Result
	 */
	@AutoLog(value = "进出厂车辆信息上传表-编辑")
	@ApiOperation(value="进出厂车辆信息上传表-编辑", notes="进出厂车辆信息上传表-编辑")
	@PutMapping(value = "/edit")
	public Result<?> edit(@RequestBody CarInformationUpload carInformationUpload) {
		carInformationUploadService.updateById(carInformationUpload);
		return Result.OK("编辑成功!");
	}

	/**
	 *   通过id删除
	 *
	 * @param id id
	 * @return Result
	 */
	@AutoLog(value = "进出厂车辆信息上传表-通过id删除")
	@ApiOperation(value="进出厂车辆信息上传表-通过id删除", notes="进出厂车辆信息上传表-通过id删除")
	@DeleteMapping(value = "/delete")
	public Result<?> delete(@RequestParam(name="id",required=true) String id) {
		carInformationUploadService.removeById(id);
		return Result.OK("删除成功!");
	}

	/**
	 *  批量删除
	 *
	 * @param ids ids
	 * @return Result
	 */
	@AutoLog(value = "进出厂车辆信息上传表-批量删除")
	@ApiOperation(value="进出厂车辆信息上传表-批量删除", notes="进出厂车辆信息上传表-批量删除")
	@DeleteMapping(value = "/deleteBatch")
	public Result<?> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
		this.carInformationUploadService.removeByIds(Arrays.asList(ids.split(",")));
		return Result.OK("批量删除成功!");
	}

	/**
	 * 通过id查询
	 *
	 * @param id id
	 * @return Result
	 */
	@AutoLog(value = "进出厂车辆信息上传表-通过id查询")
	@ApiOperation(value="进出厂车辆信息上传表-通过id查询", notes="进出厂车辆信息上传表-通过id查询")
	@GetMapping(value = "/queryById")
	public Result<?> queryById(@RequestParam(name="id",required=true) String id) {
		CarInformationUpload carInformationUpload = carInformationUploadService.getById(id);
		if(carInformationUpload==null) {
			return Result.error("未找到对应数据");
		}
		return Result.OK(carInformationUpload);
	}

    /**
    * 导出excel
    *
    * @param request 请求
    * @param carInformationUpload 对象
    */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, CarInformationUpload carInformationUpload) {
        return super.exportXls(request, carInformationUpload, CarInformationUpload.class, "进出厂车辆信息上传表");
    }

    /**
      * 通过excel导入数据
    *
    * @param request 请求
    * @param response 响应
    * @return Result
    */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        return super.importExcel(request, response, CarInformationUpload.class);
    }

	public static Date stringToDate(String dateString) {
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		LocalDateTime localDateTime = LocalDateTime.parse(dateString, formatter);

		// 将LocalDateTime转换为java.util.Date
		ZoneId zoneId = ZoneId.systemDefault();
		return Date.from(localDateTime.atZone(zoneId).toInstant());
	}

}
